// 闭包的关键点就是外面的函数有参数i但是里面的setTimeout没有参数i，于是参数就被保存在了
var loop = function (i) {
  // 里面的setTimeout没有参数,这样需要i的时候会去上层的作用域查找！
  setTimeout(() => {
    console.log(i)
  }, i * 1000)
}
for (var i = 0; i < 10; i++) {
  loop(i)
}
// 闭包
var loop = function (i) {
  setTimeout(() => {
    console.log(i)
  }, i * 1000)
}
for (var i = 0; i <= 10; i++) {
  loop(i)
}

// 利用闭包实现求平方和求立方
function makePower(power) {
  return function (number) {
    return Math.pow(number, power)
  }
}
let power2 = makePower(2)
let power3 = makePower(3)
console.log('求平方', power2(3))
console.log('求立方', power3(3))

// 缓存
const memoize = (f) => {
  // 传入的是一个函数 f
  // 参数作为键 执行结果作为值
  // 根据参数判断有没有结果
  // 一个memoize对应一个函数 所以不需要操作函数名
  let cache = {}
  // 返回的也是函数 若有缓存直接读取缓存没有缓存直接执行函数
  return (...args) => {
    // arguments 是伪数组
    // args是真的数组
    // JSON.stringify转换成为字符串作为对象的键
    let key = JSON.stringify(args)
    // 值 缓存结果 或者 执行函数 主要是把伪数组转成数组给f传递一下
    cache[key] = cache[key] || f(args)
    // 如果是arguments需要f.apply(f,arguments)
    // 返回的函数的返回值是函数的执行结果
    return cache[key]
  }
}

// 闭包私有化变量
// 闭包里面定义的变量可以使用但是外界无法获取
function Deng(wife) {
  var prepareWife = 'newWife'
  this.wife = wife
  this.changeWife = function () {
    this.wife = prepareWife
  }
}
console.log(Deng.prepareWife) // undefined
